import curses
import string
import argparse

# 定义列标签，跳过字母 'I'
columns = [chr(i) for i in range(ord('a'), ord('t') + 1) if chr(i) != 'i']

def print_board(stdscr, board, cursor_pos, current_player, use_colors):
    stdscr.clear()
    
    # 打印列标签
    stdscr.addstr(0, 4, "   ")
    for idx, col in enumerate(columns):
        stdscr.addstr(0, 4 + idx * 2, f"{col.lower()}")
    
    for row in range(19):
        # 打印行号
        stdscr.addstr(row + 1, 0, f"{row+1:2}")
        for col in range(19):
            x = 4 + col * 2
            y = row + 1
            if board[row][col] == 0:
                stdscr.addstr(y, x, "+", curses.A_DIM)
            elif board[row][col] == 1:
                if use_colors:
                    stdscr.addstr(y, x, "●", curses.color_pair(1))
                else:
                    stdscr.addstr(y, x, "●")
            elif board[row][col] == -1:
                if use_colors:
                    stdscr.addstr(y, x, "○", curses.color_pair(2))
                else:
                    stdscr.addstr(y, x, "○")
            if cursor_pos == (row, col):
                stdscr.chgat(y, x, 1, curses.A_STANDOUT)
        # 打印行号在右侧
        stdscr.addstr(row + 1, 4 + 19 * 2, f"{row+1}")
    
    # 打印底部列标签
    stdscr.addstr(20, 4, "   ")
    for idx, col in enumerate(columns):
        stdscr.addstr(20, 4 + idx * 2, f"{col.lower()}")
    
    # 显示状态信息
    player_str = "Black" if current_player == 1 else "White"
    cursor_col = columns[cursor_pos[1]]
    cursor_row = cursor_pos[0] + 1
    stdscr.addstr(22, 0, f"Current Player: {player_str}, Cursor at: {cursor_col.lower()}{cursor_row}")
    
    stdscr.refresh()

def check_win(board, player):
    # 检查水平、垂直、对角线是否连成5子
    for row in range(19):
        for col in range(19):
            if (col + 4 < 19 and 
                all(board[row][col + i] == player for i in range(5))):
                return True
            if (row + 4 < 19 and 
                all(board[row + i][col] == player for i in range(5))):
                return True
            if (row + 4 < 19 and col + 4 < 19 and 
                all(board[row + i][col + i] == player for i in range(5))):
                return True
            if (row + 4 < 19 and col - 4 >= 0 and 
                all(board[row + i][col - i] == player for i in range(5))):
                return True
    return False

def main(stdscr, file_name):
    curses.curs_set(0)  # 隐藏光标
    
    # 假设不需要颜色
    use_colors = False

    # 启用鼠标事件捕获
    curses.mousemask(curses.ALL_MOUSE_EVENTS | curses.REPORT_MOUSE_POSITION)

    board = [[0] * 19 for _ in range(19)]
    current_player = 1  # 1 for black, -1 for white
    cursor_pos = (0, 0)
    
    # 打开文件以写入棋谱
    with open(file_name, 'w') as f:
        while True:
            print_board(stdscr, board, cursor_pos, current_player, use_colors)
            
            # 获取输入
            key = stdscr.getch()

            # 处理键盘输入
            if key == curses.KEY_RIGHT:
                cursor_pos = (cursor_pos[0], min(cursor_pos[1] + 1, 18))
            elif key == curses.KEY_LEFT:
                cursor_pos = (cursor_pos[0], max(cursor_pos[1] - 1, 0))
            elif key == curses.KEY_DOWN:
                cursor_pos = (min(cursor_pos[0] + 1, 18), cursor_pos[1])
            elif key == curses.KEY_UP:
                cursor_pos = (max(cursor_pos[0] - 1, 0), cursor_pos[1])
            elif key == ord(' '):
                row, col = cursor_pos
                if board[row][col] == 0:
                    board[row][col] = current_player
                    # 记录棋步到文件
                    move = f"Player {current_player}, enter your move (e.g., a1): {columns[col]}{row+1}\n"
                    f.write(move)
                    if check_win(board, current_player):
                        stdscr.addstr(23, 0, f"Player {current_player} wins!")
                        stdscr.refresh()
                        curses.napms(3000)
                        break
                    current_player = -current_player
                else:
                    stdscr.addstr(23, 0, "This position is already occupied. Please choose another spot.", curses.A_BLINK)
                    stdscr.refresh()
                    curses.napms(1000)
            elif key == ord('q'):
                break

            # 处理鼠标输入
            elif key == curses.KEY_MOUSE:
                _, x, y, z, bstate = curses.getmouse()  # 获取鼠标事件
                # 检查是否为双击事件
                if bstate & curses.BUTTON1_DOUBLE_CLICKED:
                    # 将鼠标坐标转换为棋盘坐标
                    if y > 0 and y <= 20 and x >= 4 and x < 4 + 19 * 2:
                        row = y - 1
                        col = (x - 4) // 2
                        cursor_pos = (row, col)
                        if board[row][col] == 0:
                            board[row][col] = current_player
                            # 记录棋步到文件
                            move = f"Player {current_player}, enter your move (e.g., a1): {columns[col]}{row+1}\n"
                            f.write(move)
                            if check_win(board, current_player):
                                stdscr.addstr(23, 0, f"Player {current_player} wins!")
                                stdscr.refresh()
                                curses.napms(3000)
                                break
                            current_player = -current_player
                        else:
                            stdscr.addstr(23, 0, "This position is already occupied. Please choose another spot.", curses.A_BLINK)
                            stdscr.refresh()
                            curses.napms(1000)
                else:
                    # 处理其他鼠标事件（如单击）
                    if y > 0 and y <= 20 and x >= 4 and x < 4 + 19 * 2:
                        row = y - 1
                        col = (x - 4) // 2
                        cursor_pos = (row, col)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Gomoku game with chess notation recording.")
    parser.add_argument("file_name", help="File name to record the chess notation.")
    args = parser.parse_args()
    
    curses.wrapper(main, args.file_name)